#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct data{
	
	char user[20];
	char pwd[20];
	
	};

struct data *htable; // pointer to hash table, which will be dynamically allocated later

int size=0; // global variable to keep track of the size of table

// All the functions follow linear probing, i.e.:  h(k, i) = ( h'(k)+1 ) mod (size)

// HASH FUNCTION 1

int h(char k[], int i)
	{
	
	int l;
	int n=strlen(k);
	
	int j, sum=0;
	
	for(j=0; j<n; j++)
		sum+=(int)(k[j]); // adding all the ASCII values of the letters
	
	l=sum%size;
	
	return ((l+i)%size); // linear probing
	
	}

// Alternate hash functions given below:

/*

// HASH FUNCTION 2

int h(char k[], int i)
	{
	
	int l;
	int n=strlen(k);
	
	int j, sum=0;
	
	for(j=0; j<n; j++)
		sum+=j*(int)(k[j]); // adding j * ASCII value of letter j
	
	l=sum%size;
	return ((l+i)%size); // linear probing
	
	}

*/

/*

// HASH FUNCTION 3

int h(char k[], int i)
	{
	
	int l;
	int n=strlen(k);
	
	int j, product=1;
	
	for(j=0; j<n; j++)
		product*=(int)(k[j]); // multiplying all the ASCII values of the letters
	
	l=product%size;
	return ((l+i)%size); // linear probing
	
	}

*/

int hash_insert(char k[], char l[])
	{
	
	int i, j;
	i=0;
	
	while(i<size) // iterating the hash function till we find an empty spot
		{
		j=h(k, i);
		if(strcmp(htable[j].user, "")==0)
			{
			strcpy(htable[j].user, k);
			strcpy(htable[j].pwd, l);
			return j;
			}
		else		
			i=i+1;
		}
	
	printf("\nHash table overflow");
	return -1;
	
	}

int hash_search(char k[], char l[])
	{
	
	int i, j;
	i=0;
	
	do  // iterating the hash function till we find the element
		{
		j=h(k,i);
		if(strcmp(htable[j].user, k)==0)
			if(strcmp(htable[j].pwd, l)==0)
				return j;
		i=i+1;
		}while((strcmp(htable[j].user, "")!=0) && (i<size));
	
	return -1;
	
	}

int hash_user_search(char k[])
	{
	
	int i, j;
	i=0;
	
	do  // iterating the hash function till we find the element
		{
		j=h(k,i);
		if(strcmp(htable[j].user, k)==0)
			return j;
		i=i+1;
		}while((strcmp(htable[j].user, "")!=0) && (i<size));
	
	return -1;
	
	}

void main()
{

htable=malloc(0*sizeof(struct data));

int i, j;
char user[20], pwd[20];

FILE *f;
f=fopen("db.txt","r");

for(i=0; fscanf(f, "%s %s", user, pwd)!=EOF; i++)
	{
	size++;
	htable=realloc(htable, size*sizeof(struct data));
	hash_insert(user, pwd); // taking all values from file and inserting in the hash table
	}

for(i=0; i<size; i++)
	printf("\n%d %s %s", i, htable[i].user, htable[i].pwd);

char username[20], password[20];

printf("\n\nEnter username: ");
scanf("%s", username);

while(hash_user_search(user)==-1) // will ask for username infinitely until it gets a valid one.
	{
	printf("\nInvalid username. Enter username: ");
	scanf("%s", username);
	}

for(j=0; j<3; j++) // to restrict password attempts to 3
	{
	printf("\nEnter password: ");
	scanf("%s", password);
	if(hash_search(username, password)!=-1)
		{
		printf("\nAccess granted.\n\n");
		return;
		}
	}

printf("\nSorry, not more than 3 attempts allowed.\n\n");

}
